import Util from '../Util.js';
import TaskBar from './TaskBar.js';
import Http from './Http.js';

let pos = 1;
let maxLevel = 1;
let desktop = null;

export default class Win {
    constructor(dp) {
        desktop = dp;
    }

    build(dp, appId, flag) {
        desktop = dp;
        const id = appId;
        const app = dp.app[id];
        const width = parseFloat(app.size.width);
        const height = parseFloat(app.size.height);

        const icon = app.icon;
        const name = app.name;
        // const url = app.url;
        const projectName = app.projectName;

        let top = 3 * pos;
        let left = 3 * pos;
        let level = maxLevel;

        // 检查缓存，如果有缓存就使用缓存位置
        if (JSON.stringify(dp.app[id].cache) !== '{}') {
            const pos = dp.app[id].cache.pos;
            top = pos.top;
            left = pos.left;
            level = dp.app[id].cache.level < maxLevel ? maxLevel : dp.app[id].cache.level;
        } else {
            // 对窗口初始位置进行限制
            if (top + height > 100 || left + width > 100) {
                pos = 0;
                top = 0;
                left = 0;
            }
        }

        const win = document.createElement('div');
        // 添加样式
        win.className = 'win';
        win.id = `win_${id}`;

        // 插入元素 
        win.innerHTML = `
            <input type="radio" name="focusController" id="winCtrl_${id}" checked style="display: none;">
            <div class="win-container" id="winContainer_${id}">
                <div class="win-head">
                    <ul class="win-title">
                        <li class="win-icon"><img draggable="false" src="${icon}" alt=""></li>
                        <li class='win-name'>${name}</li>
                    </ul>
                    <ul class="win-control">
                        <li title="最小化" id="winMin_${id}"><i class="fa fa-minus"></i></li>
                        ${dp.app[id].maxable ? `<li title="最大化" id="winMax_${id}"><i class="fa fa-square"></i></li>` : ''}    
                        <li title="关闭" id="winClose_${id}" class="win-close"><i class="fa fa-times"></i></li>
                    </ul>
                </div>
                
            </div>`;
        document.body.appendChild(win);

        // 延时加载窗口资源，可以先做一个加载动画
        setTimeout(() => {
            const iframe = document.createElement('iframe');
            iframe.setAttribute('src', `${dp.app[id].url}`);
            iframe.setAttribute('name', `${projectName}-win-body`);
            iframe.setAttribute('id', `${projectName}WinBody`);

            // iframe加载完成后为内部document绑定点击事件，点击时获取焦点
            iframe.onload = function () {
                iframe.contentDocument.onclick = function () {
                    const id = win.id.substring(win.id.length - 3);
                    try {
                        document.getElementById(`winCtrl_${id}`).checked = true;
                        Win.toTop(id);
                    } catch (e) {
                        console.log(e);
                        dp.focus();
                    }
                }
            }

            document.getElementById(`winContainer_${id}`).appendChild(iframe);
        }, 300);

        if (flag === false) {
            win.setAttribute('style', `opacity: 1;width: ${width}vw; height: ${height}vh; top: ${top}vh; left: ${left}vw; z-index: ${level}`);
            if (dp.app[id].cache.status === 'minimize') {
                Win.minimize(id, false);
            }
        } else {
            win.setAttribute('style', `opacity: 0;width: 0; height: ${height}vh; top: ${top}vh; left: ${left}vw; z-index: ${level}`);

            Util.animate(win, {
                width: width,
                opacity: 1,
            }, null, 10);
        }

        desktop.app[id].cache = {
            status: 'normal',
            win: win,
            level: level,
            pos: {
                left: left,
                top: top
            }
        }

        // 添加事件
        win.addEventListener('click', (event) => {
            const id = win.id.substring(win.id.length - 3);
            try {
                document.getElementById(`winCtrl_${id}`).checked = true;
            } catch (e) {
                console.log(e);
                dp.focus();
            }
        });

        win.addEventListener('mousedown', function (event) {
            const id = win.id.substring(win.id.length - 3);
            Win.toTop(id);
            Win.winDrag(event, id);
        });

        document.getElementById(`winMin_${win.id.substring(win.id.length - 3)}`).addEventListener('click', function (event) {
            const id = win.id.substring(win.id.length - 3);
            Win.minimize(id);
        });

        document.getElementById(`winClose_${win.id.substring(win.id.length - 3)}`).addEventListener('click', function () {
            const id = win.id.substring(win.id.length - 3);
            Win.close(id);
        });

        if (dp.app[win.id.substring(win.id.length - 3)].maxable) {
            document.getElementById(`winMax_${win.id.substring(win.id.length - 3)}`).onclick = () => {
                const id = win.id.substring(win.id.length - 3);
                Win.maximize(id);
            };

            win.addEventListener('dblclick', (event) => {
                const target = Util.getTarget(event, 'DIV', 'UL');
                if (target.className === 'win-head') {
                    const id = win.id.substring(win.id.length - 3);
                    const cache = dp.app[id].cache;
                    if (cache && cache.status === 'normal') {
                        Win.maximize(id);
                    } else if (cache && cache.status === 'maximize') {
                        Win.restore(win);
                    }
                }
            });
        }

        // TODO 还有窗口的拖拽、缩放事件没有写
        maxLevel++;
        pos++;
        // 上传数据
        Http.upload('app', desktop.app);
    }

    static open(desktop, id) {
        let win = document.querySelector(`#win_${id}`);
        if (win) {
            // 已经创建，根据窗口状态做出行为
            const cache = desktop.app[id].cache;
            if (cache.status === 'minimize') {
                Win.restore(win);
                Win.toTop(id);
                TaskBar.setTopWinTask();
            } else if (cache.status === 'normal') {
                Win.toTop(id);
                TaskBar.setTopWinTask();
            }
            // else if (cache.status === 'cached') {
            //     Win.restore(win);
            //     TaskBar.addTask(id);
            //     Win.toTop(id);
            // } 
            else if (cache.status === 'maximize') {
                Win.toTop(id);
                TaskBar.setTopWinTask();
            }

        } else {
            // 没有创建就创建，传入获取到的app信息
            win = new Win();
            win.build(desktop, id);
            Win.toTop(id);
            TaskBar.addTask(id);
            setTimeout(() => {
                TaskBar.setTopWinTask();
            }, 300);
        }
    }

    static close(id) {
        const win = document.getElementById(`win_${id}`);
        const app = desktop.app[id];
        desktop.app[id].cache.level = 1;
        TaskBar.setTopWinTask();
        Util.animate(win, {
            opacity: 0,
            width: 0,
        }, () => {
            // 关闭之后不移除元素，减少dom操作，
            // 但应用的状态会被完全保留，下次打开会和以前的一摸一样
            win.remove();
            // delete winCache[id];
            // win.style['display'] = 'none';
            app.cache.status = 'cached';
            TaskBar.show();
            // 上传数据
            Http.upload('app', desktop.app);
        });

        if (app.onTaskBar === true) {
            document.getElementById(`runingTask_${id}`).className = '';
        } else {
            TaskBar.removeTask(id);
        }
    }

    static closeByName(name) {
        for (let id in desktop.app) {
            if (desktop.app[id].name === name) {
                Win.close(id);
                break;
            }
        }
    }

    static maximize(id) {
        const win = document.getElementById(`win_${id}`);

        Util.animate(win, {
            top: 0,
            left: 0,
            width: 100,
            height: 100,
        }, () => {
            // 任务栏自动隐藏
            TaskBar.hide();
        }, 15);

        const maxBtn = document.getElementById(`winMax_${id}`);
        maxBtn.title = '还原';

        maxBtn.onclick = () => {
            Win.restore(win);
        }

        desktop.app[id].cache.status = 'maximize';
        TaskBar.setTopWinTask();
        // 上传数据
        Http.upload('app', desktop.app);
    }

    static minimize(id, flag) {
        const win = document.getElementById(`win_${id}`);

        if (flag === false) {
            win.setAttribute('style', `top: ${parseFloat(document.body.clientHeight) / 11}vh; left: 2vw; width: 10vw; height: 10vh; opacity: 0; display: none;`);
        } else {
            Util.animate(win, {
                top: parseFloat(document.body.clientHeight) / 11,
                left: 2,
                width: 10,
                height: 10,
                opacity: 0
            }, () => {
                win.style['display'] = 'none';
                TaskBar.show();
                desktop.app[id].cache.level = 1;
                if (id !== Win.getTopWin()) {
                    TaskBar.setTopWinTask();
                } else {
                    TaskBar.setTopWinTask(true);
                }
            }, 10);
        }

        desktop.app[id].cache.status = 'minimize';
        // 上传数据
        Http.upload('app', desktop.app);
    }

    static restore(elem) {
        const id = elem.id.substring(elem.id.length - 3);
        const app = desktop.app[id];
        const cache = app.cache;

        elem.style.display = 'block';
        Util.animate(elem, {
            top: cache.pos.top,
            left: cache.pos.left,
            width: app.size.width,
            height: app.size.height,
            opacity: 1,
        }, null, 10);

        if (app.maxable) {
            const maxBtn = document.getElementById(`winMax_${id}`);
            maxBtn.title = '最大化';
            maxBtn.onclick = () => {
                const id = maxBtn.id.substring(maxBtn.id.length - 3);
                Win.maximize(id);
            }
        }

        desktop.app[id].cache.status = 'normal';
        Win.toTop(id);

        TaskBar.show();
        // 上传数据
        Http.upload('app', desktop.app);
    }

    static getTopWin() {
        const app = desktop.app;

        let theTopOneId = null;
        for (let id in app) {
            if (!theTopOneId && JSON.stringify(app[id].cache) !== '{}' && app[id].cache.status !== 'cached') {
                theTopOneId = id;
                continue;
            }
            if (JSON.stringify(app[id].cache) !== '{}' && app[id].cache.status !== 'cached' && app[id].cache.level > app[theTopOneId].cache.level) {
                theTopOneId = id;
            }
        }
        return theTopOneId;
    }

    static toTop(id) {
        const app = desktop.app;
        const cache = desktop.app[id].cache;

        if (JSON.stringify(cache) !== '{}' && !Win.isOnTop(id)) {
            const elem = cache.win;

            maxLevel = cache.level;

            // 得到当前最大层级
            for (let id in app) {
                if (JSON.stringify(app[id].cache) !== '{}' && app && app[id].cache.level >= maxLevel) {
                    maxLevel = app[id].cache.level;
                }
            }

            maxLevel += 5;
            elem.style['z-index'] = maxLevel;

            // 然后写入cache
            cache.level = maxLevel;
            // 上传数据
            Http.upload('app', desktop.app);
        }
        // TaskBar.setTopWinTask();
    }

    static isOnTop(id) {
        const app = desktop.app;
        const cache = desktop.app[id].cache;
        const selfId = id;

        if (JSON.stringify(cache) !== '{}') {
            for (let id in app) {
                if (cache && cache.level <= app[id].cache.level && id !== selfId) {
                    return false;
                }
            }
        }
        return true;
    }

    static winDrag(event, id) {
        if (event.target.className === 'win-head' || event.target.className === 'win-title'
            || event.target.className === 'win-name' || event.target.className === 'win-icon') {

            const cache = desktop.app[id].cache;

            if (cache && cache.status !== 'maximize') {
                const elem = cache.win;
                // 获取原始位置
                const initialWinLeft = parseFloat(Util.getStyle(elem, 'left'));
                const initialWinTop = parseFloat(Util.getStyle(elem, 'top'));

                const initialMouseLeft = event.clientX;
                const initialMouseTop = event.clientY;

                // 保存当前位置 
                let currentLeft, currentTop;

                document.onmousemove = function (event) {
                    // 给鼠标位置加上限制，超出浏览器窗口后窗口停止移动
                    if (event.clientX < document.body.clientWidth && event.clientY < document.body.clientHeight - 50 && event.clientX > 0 && event.clientY > 0) {
                        currentLeft = (initialWinLeft + event.clientX - initialMouseLeft) * 100 / document.body.clientWidth;
                        currentTop = (initialWinTop + event.clientY - initialMouseTop) * 100 / document.body.clientHeight;
                        elem.style.left = currentLeft + 'vw';
                        elem.style.top = currentTop + 'vh';
                    }
                }
                // 解绑事件，并记录新位置
                document.onmouseup = function () {
                    document.onmousemove = null;
                    cache.pos.left = currentLeft || desktop.app[id].cache.pos.left;
                    cache.pos.top = currentTop || desktop.app[id].cache.pos.top;

                    // 上传数据
                    Http.upload('app', desktop.app);
                }
            }
        }
    }

    static buildFromCache(desktop) {
        const app = desktop.app;
        let minLevel;
        // 得到最小层级
        for (let id in app) {
            if (!minLevel) {
                minLevel = app[id].cache.level;
                continue;
            }

            if (app[id].cache.level <= minLevel && app[id].cache.status == 'normal') {
                minLevel = app[id].cache.level;
            }
        }
        // 整体缩小层级
        for (let id in app) {
            if (JSON.stringify(app[id].cache) !== '{}') {
                app[id].cache.level = app[id].cache.level - minLevel + 1;
            }
        }
        // 分情况重新创建窗口
        for (let id in app) {
            // 暂时取消刷新后重建窗口，同时打开页面和多个窗口会很卡
            // 考虑在之后加入启动动画后再开启窗口重建 
            if (JSON.stringify(app[id].cache) !== '{}') {

                if (app[id].cache.status === 'normal' || app[id].cache.status === 'maximize') {
                    const win = new Win(desktop);
                    Win.open(desktop, id)
                    // win.build(desktop, id);
                    // TaskBar.addTask(id);
                    // TaskBar.setTopWinTask();
                } else if (app[id].cache.status === 'minimize') {
                    const win = new Win(desktop);
                    Win.open(desktop, id);
                    // win.build(desktop, id);
                    Win.minimize(id);
                    // TaskBar.addTask(id);
                }
            }
            if (app[id].onTaskBar === true) {
                TaskBar.fixToTaskBar(desktop, id);
            }
        }
    }

    static showWinOutline(desktop) {
        const app = desktop.app;

        for (let id in app) {
            if (JSON.stringify(app[id].cache) !== '{}' && app[id].cache.status !== 'cached') {
                const win = document.getElementById(`win_${id}`);
                win.style['background-color'] = 'transparent';
                win.style['box-shadow'] = '0 0 5px #ccc';
                win.children[1].style['opacity'] = 0;
            }
        }
    }

    static showWinOutlineExcept(desktop, id) {
        const win = document.getElementById(`win_${id}`);

        if (win && Win.isOnScreen(desktop, id)) {
            Win.showWinOutline(desktop);
            win.style['background-color'] = '#fff';
            win.style['box-shadow'] = 'none';
            win.children[1].style['opacity'] = 1;
        } else {
            Win.restoreFromTransparent(desktop);
        }
    }

    static restoreFromTransparent(desktop) {
        const app = desktop.app;

        for (let id in app) {
            if (JSON.stringify(app[id].cache) !== '{}' && app[id].cache.status !== 'cached') {
                const win = document.getElementById(`win_${id}`);
                win.style['background-color'] = '#fff';
                win.style['box-shadow'] = 'none';
                win.children[1].style['opacity'] = 1;
            }
        }
    }

    static minimizeAll(desktop) {
        const app = desktop.app;

        for (let id in app) {
            if (JSON.stringify(app[id].cache) !== '{}') {
                Win.minimize(id);
            }
        }
    }

    static isOn(desktop, id) {
        const app = desktop.app[id];
        if (JSON.stringify(app.cache) === '{}') {
            return false;
        }

        let isOn = false;
        if (app.cache.status === 'maximize' || app.cache.status === 'minimize' || app.cache.status === 'normal') {
            isOn = true;
        }
        return isOn;
    }

    static isOnScreen(desktop, id) {
        const app = desktop.app[id];
        if (app.cache.status === 'maximize' || app.cache.status === 'normal') {
            return true;
        }
        return false;
    }

    static runingWinAmount(desktop) {
        const app = desktop.app;
        let amount = 0;
        for (let id in app) {
            if (app[id].cache.status === 'maximize' || app[id].cache.status === 'minimize' || app[id].cache.status === 'normal') {
                amount++;
            }
        }
        return amount;
    }

    static clearAll(desktop) {
        const app = desktop.app;
        for (let id in app) {
            if (JSON.stringify(app[id].cache) !== '{}') {
                Win.clear(id);
            }
        }
    }

    static clear(id) {
        const win = document.getElementById(`win_${id}`);
        if (win) {
            win.remove();
            return true;
        }
        return false;
    }
}